﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Vit.Common.WinAPI;

namespace Vit.Common.Helpers
{
    public class IOHelper
    {
        public static void CopyFolder(string strFromPath, string strToPath, List<string> folderNotToCopy)
        {
            //如果源文件夹不存在，则创建
            if (!Directory.Exists(strFromPath))
            {
                Directory.CreateDirectory(strFromPath);
            }

            //取得要拷贝的文件夹名
            string strFolderName = strFromPath.Substring(strFromPath.LastIndexOf("\\") + 1, strFromPath.Length - strFromPath.LastIndexOf("\\") - 1);

            //如果目标文件夹中没有源文件夹则在目标文件夹中创建源文件夹
            if (!Directory.Exists(strToPath + "\\" + strFolderName))
            {
                Directory.CreateDirectory(strToPath + "\\" + strFolderName);
            }
            //创建数组保存源文件夹下的文件名
            string[] strFiles = Directory.GetFiles(strFromPath);

            //循环拷贝文件
            for (int i = 0; i < strFiles.Length; i++)
            {
                //取得拷贝的文件名，只取文件名，地址截掉。
                string strFileName = strFiles[i].Substring(strFiles[i].LastIndexOf("\\") + 1, strFiles[i].Length - strFiles[i].LastIndexOf("\\") - 1);
                //开始拷贝文件,true表示覆盖同名文件
                File.Copy(strFiles[i], strToPath + "\\" + strFolderName + "\\" + strFileName, true);
            }

            //创建DirectoryInfo实例
            DirectoryInfo dirInfo = new DirectoryInfo(strFromPath);
            //取得源文件夹下的所有子文件夹名称
            DirectoryInfo[] ZiPath = dirInfo.GetDirectories();
            for (int j = 0; j < ZiPath.Length; j++)
            {
                if (folderNotToCopy != null && folderNotToCopy.Contains(ZiPath[j].Name.ToLower()))
                    continue;
                //获取所有子文件夹名
                string strZiPath = strFromPath + "\\" + ZiPath[j].ToString();
                //把得到的子文件夹当成新的源文件夹，从头开始新一轮的拷贝
                CopyFolder(strZiPath, strToPath + "\\" + strFolderName, folderNotToCopy);
            }
        }

        /// <summary>
        /// 访问局域网共享目录
        /// </summary>
        /// <param name="domain">其它机器的共享目录：如 192.168.1.2</param>
        /// <param name="userName">登录其它机器的帐号</param>
        /// <param name="password">登录其它机器的密码</param>
        /// <param name="dir">共享目录名称，如 Shared</param>
        /// <returns></returns>
        public static string[] GetDomainDirecotryFiles(string domain, string userName, string password, string dir)
        {
            string[] files = null;
            ImpersonateOperation(domain, userName, password, delegate()
            {
                files = Directory.GetDirectories(string.Format(@"\\{0}\{1}", domain, dir));
            });
            return files;
        }

        /// <summary>
        /// 访问局域网共享目录
        /// </summary>
        /// <param name="domain">其它机器的共享目录：如 192.168.1.2</param>
        /// <param name="userName">登录其它机器的帐号</param>
        /// <param name="password">登录其它机器的密码</param>
        /// <param name="action">登录后按正常进行操作</param>
        public static void ImpersonateOperation(string domain, string userName, string password, Action action)
        {
            WindowsImpersonationContext impersonationContext;
            // 模拟登录
            if (ImpersonateValidUser(domain, userName, password, out impersonationContext))
            {
                action();
                // important: 在正常操作后必须undo
                impersonationContext.Undo();
            }
        }

        public static bool ImpersonateValidUser(string domain, string userName, string password, out WindowsImpersonationContext impersonationContext)
        {
            impersonationContext = null;

            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (Win32API.Network.RevertToSelf())
            {
                if (Win32API.Network.LogonUserA(userName, domain, password, Win32API.Network.LOGON32_LOGON_INTERACTIVE,
                    Win32API.Network.LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (Win32API.Network.DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            Win32API.Network.CloseHandle(token);
                            Win32API.Network.CloseHandle(tokenDuplicate);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                Win32API.Network.CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                Win32API.Network.CloseHandle(tokenDuplicate);
            return false;
        }
    }
}
